package com.richile.liu.formview;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by bot on 2017/3/1.
 * 自定义表格控件
 */

public class FormView extends View {
    /* 表格行数 */
    private int line = 4;
    /* 表格列数 */
    private int column = 6;
    /* 行高度 */
    private int lineHeight = 20;
    /* 列宽度 */
    private int columeWeight = 40;
    /* 文字大小 */
    private float textSize = 20;
    /* 列标题 */
    private ArrayList<String> titles = new ArrayList<>();
    /* 行属性 */
    private ArrayList<String> fields = new ArrayList<>();
    /* 表格数据 */
    private Map<String, ArrayList<String>> datas = new HashMap<>();

    public FormView(Context context) {
        this(context, null, 0);
    }

    public FormView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FormView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        Resources resources = context.getResources();
        /* 获取自定义属性 */
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FormView);

        /* 获取行和列的数据 */
        int fieldsResourceId = typedArray.getResourceId(R.styleable.FormView_fields, 0);
        int titlesResourceId = typedArray.getResourceId(R.styleable.FormView_titles, 0);

        if(fieldsResourceId != 0) {
            String[] strFieleds = resources.getStringArray(fieldsResourceId);
            for(String field : strFieleds){
                fields.add(field);
            }
            /* 要增加一行用来显示列标题 */
            line = fields.size() + 1;
        }

        if(titlesResourceId != 0) {
            String[] strTitles = resources.getStringArray(titlesResourceId);
            for(String title : strTitles){
                titles.add(title);
            }
            column = titles.size();
        }

        textSize = typedArray.getDimension(R.styleable.FormView_textSize, 20);

        for(int j=0; j<fields.size(); j++){
            ArrayList<String> values = new ArrayList<>();
            /* 第一列是用来显示属性的，所以列表数据列数=titles.size()-1 */
            for(int i=0; i<(titles.size() - 1); i++){
                values.add("");
            }
            datas.put(fields.get(j), values);
        }

        typedArray.recycle();

    }

    /**
     * 设置行的数据
     * @param keyLine   行的名称
     * @param values    行的数据(数组)
     * @return          是否设置成功
     */
    public boolean setValue(String keyLine, String[] values){
        ArrayList<String> strings = new ArrayList<>();

        for(String str : values){
            strings.add(str);
        }

        return setValue(keyLine, strings);
    }

    /**
     * 设置行的数据
     * @param keyLine   行的名称
     * @param values    行的数据(数组)
     * @return          是否设置成功
     */
    public boolean setValue(String keyLine, ArrayList<String> values){
        if(datas.get(keyLine) == null)
            return false;
        datas.put(keyLine, values);

        invalidate();

        return true;
    }

    /**
     * 获取行的数据
     * @param key   行的名称
     * @return      返回行的数据
     */
    public ArrayList<String> getValue(String key){
        return datas.get(key);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        /* 取平均高度和宽度 */
        lineHeight = getHeight() / line;
        columeWeight = getWidth() / column;

        /* 用于画线的画笔 */
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        /* 设置线的宽度 */
        paint.setStrokeWidth(1);

        /* 用于写列表中数据的画笔 */
        Paint paintText = new Paint();
        paintText.setColor(Color.BLACK);
        paintText.setStyle(Paint.Style.FILL);
        paintText.setTextSize(textSize);

        /* 获取字体信息 */
        Paint.FontMetricsInt fontMetricsInt = paintText.getFontMetricsInt();
        /* 文字为水平居中*/
        paintText.setTextAlign(Paint.Align.CENTER);

        /* 给第一行画上背景颜色 */
        Paint paintTitles = new Paint();
        paintTitles.setColor(0xffd3f0e0);
        canvas.drawRect(new Rect(0, 0, columeWeight*column, lineHeight), paintTitles);

        /* 给第一列画上背景颜色 */
        Paint painFields = new Paint();
        painFields.setColor(0xff9fd5b7);
        canvas.drawRect(new Rect(0, lineHeight, columeWeight, lineHeight*line), painFields);

        /* 开始画线 */
        for(int i=0; i<line+1; i++){
            /* 画水平线 */
            canvas.drawLine(0, i*lineHeight, columeWeight*column, i*lineHeight, paint);
        }

        for(int i=0; i<column+1; i++){
            /* 画竖直线 */
            canvas.drawLine(i*columeWeight, 0, i*columeWeight, line*lineHeight, paint);
        }

        /* 填充文字 */
        for(int j=0; j<line; j++) {
            /* 写列的文字 */
            for(int i=0; i<column; i++){
                Rect targetRect = new Rect(i * columeWeight, j * lineHeight,
                        (i + 1) * columeWeight, (j + 1) * lineHeight);
                /* 基线 =（目标区域中心点的y值-字体中心的y值） */
                int baseline = (targetRect.bottom + targetRect.top - fontMetricsInt.bottom - fontMetricsInt.top) / 2;
                if(j == 0){
                    /* 第一行显示标题 */
                    canvas.drawText(titles.get(i), targetRect.centerX(), baseline, paintText);
                }else{
                    /* 第一列显示字段 */
                    if(i == 0){
                        canvas.drawText(fields.get(j-1), targetRect.centerX(), baseline, paintText);
                    }
                    /* 其他列显示字段值 */
                    else{
                        try {
                            String str = datas.get(fields.get(j-1)).get(i-1);
                            canvas.drawText((str == null)?"":str, targetRect.centerX(), baseline, paintText);
                        }catch (NullPointerException e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
